#include "kdcdiscmodel.h"

#include <QList>
#include <QDebug>
#include <KLocale>
#include <KIcon>
#include <kdclib.h>


#include <kdcobject.h>


KDCDiscModel::KDCDiscModel( QObject *aParent ) : QAbstractItemModel( aParent )
{

}

KDCDiscModel::~KDCDiscModel()
{
	for ( int i=0; i<pDiscs.size(); ++i )
		deletePtr( pDiscs.at( i ) );
}

int KDCDiscModel::rowCount( const QModelIndex &aParent ) const
{
    KDCObject *obj = NULL;
    if ( aParent.isValid() && aParent.column() == 0 )
        obj = static_cast<KDCObject*>( aParent.internalPointer() );
    if ( obj )
	{
		switch( obj->object() )
		{
			case KDC::VTS: return static_cast<KDCVTS*>( obj )->movies().size();
			case KDC::Disc: 
			{
				KDCDisc *disc = static_cast<KDCDisc*>( obj );
				switch( disc->type() )
				{
					case KDC::DVD: return disc->vts().size() + ( ( disc->menu() ) ? 1 : 0 );
					default: return disc->movies().size();
				}
			}
			default: return 0;
		}
	}
    return pDiscs.size();
}

QVariant KDCDiscModel::data( const QModelIndex &aIndex, int aRole ) const
{
    if ( aIndex.isValid() )
	{
        KDCObject *obj = static_cast<KDCObject*>( aIndex.internalPointer() );
		if ( aRole == Qt::DisplayRole )
			return obj->title();
		else
			if ( aRole == Qt::DecorationRole )
				return obj->icon();
	}
    return QVariant();
}

QModelIndex KDCDiscModel::parent( const QModelIndex &aIndex ) const
{
    if ( !aIndex.isValid() )
        return QModelIndex();

    KDCObject *obj = static_cast<KDCObject*>( aIndex.internalPointer() );
	if ( obj->object() == KDC::Disc )
		return QModelIndex();   
    else
	{
		int row = 0;
		if ( obj->object() == KDC::VTS )
			row = pDiscs.indexOf( static_cast<KDCDisc*>( obj->parent() ) );
		else
			if ( obj->object() == KDC::Menu )
				row = pDiscs.indexOf( static_cast<KDCDisc*>( obj->parent() ) );
		else
			if ( obj->object() == KDC::Movie && obj->parent()->object() == KDC::VTS )
				row = static_cast<KDCDisc*>( obj->parent()->parent() )->vts().indexOf( static_cast<KDCVTS*>( obj->parent() ) );
		else
			if ( obj->object() == KDC::Movie && obj->parent()->object() == KDC::Disc )
				row = pDiscs.indexOf( static_cast<KDCDisc*>( obj->parent() ) );
        return createIndex( row, 0, obj->parent() );
	}
}

int KDCDiscModel::columnCount( const QModelIndex &aParent ) const
{
    return 1;
}

QModelIndex KDCDiscModel::index( int aRow, int aColumn, const QModelIndex &aParent ) const
{
    if ( !hasIndex( aRow, aColumn, aParent ) )
        return QModelIndex();
	KDCObject *obj = NULL;
    if ( aParent.isValid() )
        obj = static_cast<KDCObject*>( aParent.internalPointer() );

	KDCObject *child = NULL;
	if ( !obj )
		child = pDiscs.at( aRow );
	else
	{
		if ( obj->object() == KDC::VTS )
			child = static_cast<KDCVTS*>( obj )->movies().at( aRow );
		else
			if ( obj->object() == KDC::Disc )
			{
				KDCDisc *disc = static_cast<KDCDisc*>( obj );
				switch( disc->type() )
				{
					case KDC::DVD:
					{
						if ( !disc->menu() )
							child = disc->vts().at( aRow );
						else
						{
							if ( aRow == 0 )
								child = disc->menu();
							else
								child = disc->vts().at( aRow - 1 );
						}
						break;
					}
					default: child = disc->movies().at( aRow ); break;
				}
			}
	}

    if ( child )
        return createIndex( aRow, aColumn, child );
    else
        return QModelIndex();
}

Qt::ItemFlags KDCDiscModel::flags(const QModelIndex &aIndex ) const
{
    if ( aIndex.isValid() )
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    return QAbstractItemModel::flags( aIndex );
}

QVariant KDCDiscModel::headerData( int aSection, Qt::Orientation aOrientation, int aRole ) const
{
    if ( aOrientation == Qt::Horizontal && aRole == Qt::DisplayRole )
        return i18n( "Discs structure" );
    return QAbstractItemModel::headerData( aSection, aOrientation, aRole );
}

void KDCDiscModel::addObject( KDCDisc *aDisc, KDCMenu *aMenu )
{
	QModelIndex parent = indexFromObject( aDisc );
	if ( parent.isValid() )
	{
		beginInsertRows( parent, rowCount( parent ), rowCount( parent ) );
		aDisc->add( aMenu );
		endInsertRows();
	}
}

void KDCDiscModel::addObject( KDCDisc *aDisc, KDCVTS *aVts )
{
	QModelIndex parent = indexFromObject( aDisc );
	if ( parent.isValid() )
	{
		beginInsertRows( parent, rowCount( parent ), rowCount( parent ) );
		aDisc->add( aVts );
		endInsertRows();
	}
}

void KDCDiscModel::addObject( KDCDisc *aDisc, KDCMovie *aMovie )
{
	QModelIndex parent = indexFromObject( aDisc );
	if ( parent.isValid() )
	{
		beginInsertRows( parent, rowCount( parent ), rowCount( parent ) );
		aDisc->add( aMovie );
		if ( aDisc->type() == KDC::DVD )
			setupDVD( aMovie );
		endInsertRows();
	}
}

void KDCDiscModel::addObject( KDCDisc *aDisc )
{
	beginInsertRows( QModelIndex(), rowCount(), rowCount() );
	pDiscs.append( aDisc );
	endInsertRows();
}

void KDCDiscModel::addObject( KDCVTS *aVts, KDCMovie *aMovie )
{
	QModelIndex parent = indexFromObject( aVts );
	if ( parent.isValid() )
	{
		beginInsertRows( parent, rowCount( parent ), rowCount( parent ) );
		aVts->add( aMovie );
		endInsertRows();
	}
}
	
void KDCDiscModel::removeObject( KDCDisc *aDisc, KDCMenu *aMenu, bool aDelete )
{
	QModelIndex parent = indexFromObject( aDisc );
	beginRemoveRows( parent, 0, 0 );
	aDisc->remove( aMenu );
	if ( aDelete )
		deletePtr( aMenu );
	endRemoveRows();
}

void KDCDiscModel::removeObject( KDCDisc *aDisc, KDCVTS *aVts, bool aDelete )
{
	QModelIndex parent = indexFromObject( aDisc );
	int row = aDisc->vts().indexOf( aVts ) + ( ( aDisc->menu() ) ? 1 : 0 );
	beginRemoveRows( parent, row, row );
	aDisc->remove( aVts );
	if ( aDelete )
		deletePtr( aVts );
	endRemoveRows();
}

void KDCDiscModel::removeObject( KDCDisc *aDisc, KDCMovie *aMovie, bool aDelete )
{
	QModelIndex parent = indexFromObject( aDisc );
	int row = aDisc->movies().indexOf( aMovie );
	beginRemoveRows( parent, row, row );
	aDisc->remove( aMovie );
	if ( aDelete )
		deletePtr( aMovie );
	endRemoveRows();
}

void KDCDiscModel::removeObject( KDCDisc *aDisc, bool aDelete )
{
	beginRemoveRows( QModelIndex(), pDiscs.indexOf( aDisc ), pDiscs.indexOf( aDisc ) );
	pDiscs.removeOne( aDisc );
	if ( aDelete )
		deletePtr( aDisc );
	endRemoveRows();
}

void KDCDiscModel::removeObject( KDCVTS *aVts, KDCMovie *aMovie, bool aDelete )
{
	QModelIndex parent = indexFromObject( aVts );
	int row = aVts->movies().indexOf( aMovie );
	beginRemoveRows( parent, row, row );
	aVts->remove( row );
	if ( aDelete )
		deletePtr( aMovie );
	endRemoveRows();
}

KDCObject* KDCDiscModel::objectFromIndex( const QModelIndex &aIndex ) const
{
	return static_cast<KDCObject*>( aIndex.internalPointer() );
}

QModelIndex KDCDiscModel::indexFromObject( KDCObject *aObject ) const
{
	KDCDisc *disc = getDisc( aObject );
	if ( disc )
	{
		int idx = pDiscs.indexOf( disc );
		if ( idx > -1 )
		{
			QModelIndex parent = index( idx, 0 );
			if ( aObject == disc )
				return parent;
			else
				if ( aObject->object() == KDC::Menu )
					return index( 0, 0, parent );
			else
				if ( aObject->object() == KDC::VTS )
					return index( disc->vts().indexOf( static_cast<KDCVTS*>( aObject ) ) + ( ( disc->menu() ) ? 1 : 0 ), 0, parent );
			else
			{
				if ( disc->type() == KDC::DVD )
				{
					if ( aObject->parent()->object() == KDC::VTS )
					{
						parent = index( disc->vts().indexOf( static_cast<KDCVTS*>( aObject->parent() ) ) + ( ( disc->menu() ) ? 1 : 0 ), 0, parent );
						return index( static_cast<KDCVTS*>( aObject->parent() )->movies().indexOf( static_cast<KDCMovie*>( aObject ) ), 0, parent );
					}
				}
				else
					return index( disc->movies().indexOf( static_cast<KDCMovie*>( aObject ) ), 0, parent );
			}
		}
	}
	return QModelIndex();
}

void KDCDiscModel::setupDVD( KDCMovie *aMovie ) const
{
	aMovie->video()->setCodec( KDC::MPEG2 );
	if ( aMovie->videoFormat() == KDC::PAL )
	{
		if ( aMovie->metaData()->videoMetaData()->isDVDPALVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 2500 );
			aMovie->video()->setResolution( 720, 576 );
			aMovie->video()->setAspectRatio( KDC::WideScreen );
			aMovie->setVideoFormat( KDC::PAL );
		}
		if ( !aMovie->metaData()->audioMetaData().isEmpty() )
		{
			KDCAudioMetaData *aMetaData;
			KDCAudio *aStream; 
			for( int i=0; i<aMovie->metaData()->audioMetaData().size(); ++i )
			{
				aMetaData = aMovie->metaData()->audioMetaData().at( i );
				aStream = aMovie->audio().at( i );
				if ( aMetaData->isDVDPALAudio() )
					aStream->setMode( KDC::Copy );
				else
				{
					if ( aMetaData->channelCount() == 6 )
					{
						aStream->setCodec( KDC::AC3 );
						aStream->setChannelCount( 6 );
						aStream->setBitrate( 384 );
					}
					else
					{
						aStream->setChannelCount( 2 );
						aStream->setCodec( aMetaData->codec() );
						aStream->setBitrate( 128 );
					}
					aStream->setMode( KDC::Resample );
					aStream->setDelay( 0 );
				}
			}
		}	
	}
	else //NTSC
	{
		if ( aMovie->metaData()->videoMetaData()->isDVDNTSCVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 2500 );
			aMovie->video()->setResolution( 720, 480 );
			aMovie->video()->setAspectRatio( KDC::WideScreen );
			aMovie->setVideoFormat( KDC::NTSC );
		}
		if ( !aMovie->metaData()->audioMetaData().isEmpty() )
		{
			KDCAudioMetaData *aMetaData;
			KDCAudio *aStream; 
			for( int i=0; i<aMovie->metaData()->audioMetaData().size(); ++i )
			{
				aMetaData = aMovie->metaData()->audioMetaData().at( i );
				aStream = aMovie->audio().at( i );
				if ( aMetaData->isDVDNTSCAudio() )
					aStream->setMode( KDC::Copy );
				else
				{
					if ( aMetaData->channelCount() == 6 )
					{
						aStream->setCodec( KDC::AC3 );
						aStream->setBitrate( 384 );
					}
					else
					{
						aStream->setCodec( KDC::AC3 );
						aStream->setChannelCount( 2 );
						aStream->setBitrate( 128 );
					}
					aStream->setMode( KDC::Resample );
					aStream->setDelay( 0 );
				}
			}
		}
	}
}

void KDCDiscModel::setupSVCD( KDCMovie *aMovie ) const
{
	aMovie->video()->setCodec( KDC::MPEG2 );
	if ( aMovie->videoFormat() == KDC::PAL )
	{
		if ( aMovie->metaData()->videoMetaData()->isSVCDPALVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 1500 );
			aMovie->video()->setResolution( 480, 576 );
			aMovie->video()->setAspectRatio( KDC::LetterBox );
			aMovie->setVideoFormat( KDC::PAL );
		}
	}
	else //NTSC
	{
		if ( aMovie->metaData()->videoMetaData()->isSVCDNTSCVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 1500 );
			aMovie->video()->setResolution( 480, 480 );
			aMovie->video()->setAspectRatio( KDC::LetterBox );
			aMovie->setVideoFormat( KDC::NTSC );
		}
	}
	if ( !aMovie->metaData()->audioMetaData().isEmpty() )
	{
		KDCAudioMetaData *aMetaData;
		KDCAudio *aStream; 
		for( int i=0; i<aMovie->metaData()->audioMetaData().size(); ++i )
		{
			aMetaData = aMovie->metaData()->audioMetaData().at( i );
			aStream = aMovie->audio().at( i );
			if ( aMetaData->isSVCDAudio() )
				aStream->setMode( KDC::Copy );
			else
			{
				aStream->setCodec( KDC::MP2 );
				aStream->setChannelCount( 2 );
				aStream->setBitrate( 224 );
				aStream->setMode( KDC::Resample );
				aStream->setDelay( 0 );
			}
		}
	}
}

void KDCDiscModel::setupVCD( KDCMovie *aMovie ) const
{
	aMovie->video()->setCodec( KDC::MPEG2 );
	if ( aMovie->videoFormat() == KDC::PAL )
	{
		if ( aMovie->metaData()->videoMetaData()->isVCDPALVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 1150 );
			aMovie->video()->setResolution( 352, 288 );
			aMovie->video()->setAspectRatio( KDC::LetterBox );
			aMovie->setVideoFormat( KDC::PAL );
		}
	}
	else //NTSC
	{
		if ( aMovie->metaData()->videoMetaData()->isVCDNTSCVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 1150 );
			aMovie->video()->setResolution( 352, 240 );
			aMovie->video()->setAspectRatio( KDC::LetterBox );
			aMovie->setVideoFormat( KDC::NTSC );
		}
	}
	if ( !aMovie->metaData()->audioMetaData().isEmpty() )
	{
		KDCAudioMetaData *aMetaData;
		KDCAudio *aStream; 
		for( int i=0; i<aMovie->metaData()->audioMetaData().size(); ++i )
		{
			aMetaData = aMovie->metaData()->audioMetaData().at( i );
			aStream = aMovie->audio().at( i );
			if ( aMetaData->isVCDAudio() )
				aStream->setMode( KDC::Copy );
			else
			{
				aStream->setCodec( KDC::MP2 );
				aStream->setChannelCount( 2 );
				aStream->setBitrate( 224 );
				aStream->setMode( KDC::Resample );
				aStream->setDelay( 0 );
			}
		}
	}
}

void KDCDiscModel::setupCVD( KDCMovie *aMovie ) const
{
	aMovie->video()->setCodec( KDC::MPEG2 );
	if ( aMovie->videoFormat() == KDC::PAL )
	{
		if ( aMovie->metaData()->videoMetaData()->isCVDPALVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 1500 );
			aMovie->video()->setResolution( 352, 576 );
			aMovie->video()->setAspectRatio( KDC::LetterBox );
			aMovie->setVideoFormat( KDC::PAL );
		}
	}
	else //NTSC
	{
		if ( aMovie->metaData()->videoMetaData()->isCVDNTSCVideo() )
			aMovie->video()->setMode( KDC::Copy );
		else
		{
			aMovie->video()->setMode( KDC::Resample );
			aMovie->video()->setBitrate( 1500 );
			aMovie->video()->setResolution( 352, 480 );
			aMovie->video()->setAspectRatio( KDC::LetterBox );
			aMovie->setVideoFormat( KDC::NTSC );
		}
	}
	if ( !aMovie->metaData()->audioMetaData().isEmpty() )
	{
		KDCAudioMetaData *aMetaData;
		KDCAudio *aStream; 
		for( int i=0; i<aMovie->metaData()->audioMetaData().size(); ++i )
		{
			aMetaData = aMovie->metaData()->audioMetaData().at( i );
			aStream = aMovie->audio().at( i );
			if ( aMetaData->isCVDAudio() )
				aStream->setMode( KDC::Copy );
			else
			{
				aStream->setCodec( KDC::MP2 );
				aStream->setChannelCount( 2 );
				aStream->setBitrate( 224 );
				aStream->setMode( KDC::Resample );
				aStream->setDelay( 0 );
			}
		}
	}
}
